﻿using Newtonsoft.Json;
using System.Collections.Generic;
using T.FAS.Runtime.DataAccess.Common;
using T.FAS.Runtime.DataAccess.SQLDom;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.FAS.Runtime.Metadata.Entity;

namespace T.FAS.Runtime.DataAccess.Engine
{
    /// <summary>
    /// 统一数据访问服务帮助类
    /// </summary>
    internal class DACControlContextHelper
    {
        /// <summary>
        /// 构造默认控制参数上下文
        /// </summary>
        /// <param name="extParams">额外控制参数，类型为字典</param>
        /// <param name="metadata">元数据实例</param>
        /// <param name="timestamp">时间戳</param>
        /// <returns></returns>
        public static SqlExecuteControlContext GetDefaultControlContext(Dictionary<string, object> extParams, IMetaDataContent metadata, string timestamp = null)
        {
            SqlExecuteControlContext controlContext = new SqlExecuteControlContext
            {
                Timeout = 0,
                IsCheckTimestamp = true,
                MetaDataType = GetMetaTypeInfo(metadata),
                MetaInfo = metadata,
            };

            //处理额外控制参数
            if (extParams != null)
            {
                // 
                if (TryGetValue(extParams, DACConst.ExtSetting, out string json) && !string.IsNullOrEmpty(json))
                {
                    QueryExtSetting setting;
                    try
                    {
                        setting = JsonConvert.DeserializeObject<QueryExtSetting>(json);
                        controlContext.InitMaskControl(true, setting.IsAll, setting.Columns);
                    }
                    catch
                    {
                    }
                }

                //批量更新时，不再校验时间戳条件 

                if (TryGetValue(extParams, DACConst.CDO.IsBatchUpdate, out bool isBatchUpdate) && isBatchUpdate)
                {
                    controlContext.IsCheckTimestamp = false;
                }

                try
                {
                    //国际化语言设置配置，CDO\CRUD操作都用
                    if (extParams.ContainsKey(DACConst.ExtParamSwitch.TargetLanguageList))
                    {
                        controlContext.SpecifiedLanguages = extParams[DACConst.ExtParamSwitch.TargetLanguageList] as List<string>;
                    }
                    if (extParams.ContainsKey(DACConst.ExtParamSwitch.InternationalMode))
                    {
                        controlContext.InternationalMode = (InternationalMode)(extParams[DACConst.ExtParamSwitch.InternationalMode]);
                    }
                }
                catch
                {

                }
            }

            if (string.IsNullOrEmpty(timestamp))
            {
                controlContext.Timestamp = timestamp;
            }

            //构造鉴权上下文
            if (IsNeedAuthAndTryGetAuthResult(metadata, out List<ColumnPermissionView> result))
            {
                controlContext.InitAuthControl(true, result);
            }

            return controlContext;
        }

        /// <summary>
        /// 获取默认的extParam，主要针对CDO.Query默认传入
        /// </summary>
        /// <returns></returns>
        public static Dictionary<string, object> BuildDefultExtParams()
        {
            string json = JsonConvert.SerializeObject(
                new QueryExtSetting
                {
                    IsAll = true,
                    Columns = null
                });
            return new Dictionary<string, object>
            {
                { DACConst.ExtSetting, json}
            };
        }

        #region Private Funcs
        /// <summary>
        /// 获取元数据类型
        /// </summary>
        /// <param name="metadata"></param>
        /// <returns></returns>
        private static string GetMetaTypeInfo(IMetaDataContent metadata)
        {
            if (!string.IsNullOrEmpty(metadata.MetaData?.MetaTypeID)) return metadata.MetaData.MetaTypeID;
            if (metadata is DataObject)
            {
                return nameof(DataObject);
            }
            else if (metadata is CompositeDataObject)
            {
                return nameof(CompositeDataObject);
            }
            else if (metadata is DataQuery)
            {
                return nameof(DataQuery);
            }
            return null;
        }

        /// <summary>
        /// 尝试获取值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dict"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool TryGetValue<T>(Dictionary<string, object> dict, string key, out T value)
        {
            value = default(T);
            if (dict == null)
                return false;
            try
            {
                if (dict.ContainsKey(key))
                {
                    value = (T)dict[key];
                    return true;
                }
                return false;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 判断是否需要走鉴权逻辑，同时尝试获取元数据授权结果
        /// </summary>
        /// <returns>true:需要鉴权，false:不需要</returns>
        public static bool IsNeedAuthAndTryGetAuthResult(IMetaDataContent metadata, out List<ColumnPermissionView> result)
        {
            result = null;
            if (metadata is CompositeDataObject cdo)
            {
                return AuthTool.IsNeedAuthAndTryGetAuthResult(cdo, out result);
            }
            else if (metadata is DataQuery dq)
            {
                return AuthTool.IsNeedAuthAndTryGetAuthResult(dq, out result);
            }
            return false;
        }
        #endregion
    }

    public class QueryExtSetting
    {
        public bool IsAll { get; set; }
        public List<string> Columns { get; set; }
    }
}
